iT邦幫忙

2022 iThome 鐵人賽

DAY 28
0

接下來的內容十分困難,如果有誤請見諒。一般來說,在遇到併發問題,最常遇到的困擾是多個不同的執行緒需要讀寫相同的資料,這時候發生競爭,就會產生意想不到的結果。舉個例子來說,主廚正在準備餐點,嚐了一口後覺得不夠鹹,一聲令下叫學徒幫忙加一匙鹽,結果學徒A跟學徒B接收到命令後開始加鹽程序,結果不小心加到同一道菜,於是乎客人覺得太鹹了,導致主廚被開除的人倫悲劇(我到底在說什麼…..

處理併發

一般來說再處理併發有幾種方式

  1. Lock

    這應該是大家比較熟悉的方式,我們可以在執行緒讀寫時幫資料加上鎖,當執行完成時才解開來讓其他的執行緒能夠使用。

    class LockSample
    {
    		private readonly object lockObject = new object();
    		public void UpdateStatus(Sample sample)
    		{
    				lock(lockObject)
    				{
    						sample.Status = !sample.Status;
    				}
    		}
    }
    

    像上面的範例就是一段修改狀態的程式,並且將執行緒鎖住。使用鎖的好處是直覺簡單,在鎖失效之前都能保證只有單一執行緒能夠進行讀寫,同時也代表了其他的執行緒需要等到解鎖才能夠繼續作業,為了解決一個問題反而可能衍生其他問題問題像是DeadLock之類的,不過只要能夠確保沒有問題Lock仍然是一個簡單易用的好方法。

  2. Software Transactional Memory

    第二個方法是普遍的函數式語言常用的,類似資料庫中的交易,搭配函數式的一些特性讓併發容易處理,以兩個執行緒(A/B)需讀取並更新相同欄位(ColumnA)為例,需要歷經以下過程

    1. 執行緒A在更新時會先將結果記錄在記憶體中,並不直接更新
    2. 執行緒B先讀取記憶體中有沒有更新紀錄,沒有的話會從原來的ColumnA讀取要更新的值,並且將更新結果記錄在記憶體(是的,執行緒A也會先從記憶體中讀取)
    3. 每個執行緒結束作業時,會比對記憶體中的值與原來的ColumnA是否相符,否則不執行更新
    4. 如果不相符的話就會重做一次作業,因為函數式語言保證都是純函數,沒有額外的狀態改變,可以無限次重複執行

    是不是跟資料庫的交易很像呢?(如果失敗就rollback)

  3. Actor model

    最後一個模型是將作業抽象成物件導向中不同的對象,並且搭配函數導向中的一些觀念設計的模型,我們稱每個對象都是一個Actor

    • 每個Actor只知道自身的狀態,換句話說,每個Actor的作業都是獨立執行的
    • Actor之間不共享狀態,只使用訊息方式傳遞資訊

    透過訊息方式傳遞資訊的意思是,如果兩個Actor需要共同的狀態,那就複製一份過去,每個Actor都保有自己所需的資訊,就可以避免競爭問題。Actor model其實主要是用在分散式系統,不同機器之間依靠通訊協作,如果放在本機上就像是多個執行緒之間依靠通訊共享資訊。是不是非常抽象呢?明天我們會對他有近一步介紹。


上一篇
Day27. Lazy Evaluation
下一篇
Day29. Actor model
系列文
Functional Programming with C#30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言